home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / ka9q_src.arc / SLIP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-30  |  10.0 KB  |  439 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "config.h"
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "iface.h"
  9. #include "timer.h"
  10.  
  11. #ifdef    SLFP
  12. #include "ip.h"
  13. #include "slfp.h"
  14. #endif
  15.  
  16. #include "ax25.h"
  17. #include "slip.h"
  18. #include "nrs.h"
  19. #ifdef UNIX    /* BSD or SYS5 */
  20. #include "unix.h"
  21. #else
  22. # ifdef ATARI_ST
  23. #  include "st.h"
  24. # else
  25. #  include "pc.h"
  26. #  include "asy.h"
  27. # endif        /* ATARI_ST */
  28. #endif        /* BSD or SYS5 */
  29. #include "trace.h"
  30.  
  31. int asy_ioctl();
  32. int kiss_ioctl();
  33. int slip_send();
  34. int doslip();
  35. int asy_output();
  36.  
  37. #ifdef    SLFP
  38. int doslfp();
  39. int slfp_raw();
  40. int slfp_send();
  41. int slfp_recv();
  42. int slfp_init();
  43. #endif
  44.  
  45. /* Slip level control structure */
  46. struct slip slip[ASY_MAX];
  47.  
  48. /* Send routine for point-to-point slip
  49.  * This is a trivial function since there is no slip link-level header
  50.  */
  51. int
  52. slip_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  53. struct mbuf *bp;        /* Buffer to send */
  54. struct interface *interface;    /* Pointer to interface control block */
  55. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  56. char precedence;
  57. char delay;
  58. char throughput;
  59. char reliability;
  60. {
  61.     if(interface == NULLIF){
  62.         free_p(bp);
  63.         return;
  64.     }
  65.     dump(interface,IF_TRACE_OUT,TRACE_IP,bp);
  66.     (*interface->raw)(interface,bp);
  67. }
  68. /* Send a raw slip frame -- also trivial */
  69. slip_raw(interface,bp)
  70. struct interface *interface;
  71. struct mbuf *bp;
  72. {
  73.     /* Queue a frame on the slip output queue and start transmitter */
  74.     slipq(interface->dev,bp);
  75. }
  76. /* Encode a raw packet in slip framing, put on link output queue, and kick
  77.  * transmitter
  78.  */
  79. static
  80. slipq(dev,bp)
  81. int16 dev;        /* Serial line number */
  82. struct mbuf *bp;    /* Buffer to be sent */
  83. {
  84.     register struct slip *sp;
  85.     struct mbuf *slip_encode();
  86.  
  87.     if((bp = slip_encode(bp)) == NULLBUF)
  88.         return;    
  89.  
  90.     sp = &slip[dev];
  91.     enqueue(&sp->sndq,bp);
  92.     sp->sndcnt++;
  93.     if(sp->tbp == NULLBUF)
  94.         asy_start(dev);
  95. }
  96. /* Start output, if possible, on asynch device dev */
  97. static
  98. asy_start(dev)
  99. int16 dev;
  100. {
  101.     register struct slip *sp;
  102.  
  103.     if(!stxrdy(dev))
  104.         return;        /* Transmitter not ready */
  105.  
  106.     sp = &slip[dev];
  107.     if(sp->tbp != NULLBUF){
  108.         /* transmission just completed */
  109.         free_p(sp->tbp);
  110.         sp->tbp = NULLBUF;
  111.     }
  112.     if(sp->sndq == NULLBUF)
  113.         return;    /* No work */
  114.  
  115.     sp->tbp = dequeue(&sp->sndq);
  116.     sp->sndcnt--;
  117.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  118. }
  119. /* Encode a packet in SLIP format */
  120. static
  121. struct mbuf *
  122. slip_encode(bp)
  123. struct mbuf *bp;
  124. {
  125.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  126.     register char *cp;
  127.     register int cnt;
  128.     char c;
  129.  
  130.     /* Allocate output mbuf that's twice as long as the packet.
  131.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  132.      */
  133.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  134.     if(lbp == NULLBUF){
  135.         /* No space; drop */
  136.         free_p(bp);
  137.         return NULLBUF;
  138.     }
  139.     cp = lbp->data;
  140.     cnt = 0;
  141.  
  142.     /* Flush out any line garbage */
  143.     *cp++ = FR_END;
  144.     cnt++;
  145.  
  146.     /* Copy input to output, escaping special characters */
  147.     while(pullup(&bp,&c,1) == 1){
  148.         switch(c & 0xff){
  149.         case FR_ESC:
  150.             *cp++ = FR_ESC;
  151.             *cp++ = T_FR_ESC;
  152.             cnt += 2;
  153.             break;
  154.         case FR_END:
  155.             *cp++ = FR_ESC;
  156.             *cp++ = T_FR_END;
  157.             cnt += 2;
  158.             break;
  159.         default:
  160.             *cp++ = c;
  161.             cnt++;
  162.         }
  163.     }
  164.     *cp++ = FR_END;
  165.     cnt++;
  166.     lbp->cnt = cnt;
  167.     return lbp;
  168. }
  169. /* Process incoming bytes in SLIP format
  170.  * When a buffer is complete, return it; otherwise NULLBUF
  171.  */
  172. static
  173. struct mbuf *
  174. slip_decode(dev,c)
  175. int16 dev;    /* Slip unit number */
  176. char c;        /* Incoming character */
  177. {
  178.     struct mbuf *bp;
  179.     register struct slip *sp;
  180.  
  181.     sp = &slip[dev];
  182.     switch(c & 0xff){
  183.     case FR_END:
  184.         bp = sp->rbp;
  185.         sp->rbp = NULLBUF;
  186.         sp->rcnt = 0;
  187.         return bp;    /* Will be NULLBUF if empty frame */
  188.     case FR_ESC:
  189.         sp->escaped = 1;
  190.         return NULLBUF;
  191.     }
  192.     if(sp->escaped){
  193.         sp->escaped = 0;
  194.         switch(c & 0xff){
  195.         case T_FR_ESC:
  196.             c = FR_ESC;
  197.             break;
  198.         case T_FR_END:
  199.             c = FR_END;
  200.             break;
  201.         default:
  202.             sp->errors++;
  203.             break;        /* DG2KK: from .16 */
  204.         }
  205.     }
  206.     /* We reach here with a character for the buffer;
  207.      * make sure there's space for it
  208.      */
  209.     if(sp->rbp == NULLBUF){
  210.         /* Allocate first mbuf for new packet */
  211.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  212.             return NULLBUF; /* No memory, drop */
  213.         sp->rcp = sp->rbp->data;
  214.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  215.         /* Current mbuf is full; link in another */
  216.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  217.             /* No memory, drop whole thing */
  218.             free_p(sp->rbp);
  219.             sp->rbp = NULLBUF;
  220.             sp->rcnt = 0;
  221.             return NULLBUF;
  222.         }
  223.         sp->rbp1 = sp->rbp1->next;
  224.         sp->rcp = sp->rbp1->data;
  225.     }
  226.     /* Store the character, increment fragment and total
  227.      * byte counts
  228.      */
  229.     *sp->rcp++ = c;
  230.     sp->rbp1->cnt++;
  231.     sp->rcnt++;
  232.     return NULLBUF;
  233. }
  234. /* Process SLIP line I/O */
  235. int
  236. doslip(interface)
  237. struct interface *interface;
  238. {
  239.     char c;
  240.     struct mbuf *bp;
  241.     int16 dev;
  242.     int16 asy_recv();
  243.  
  244.     dev = interface->dev;
  245.     /* Process any pending input */
  246.     while(asy_recv(dev,&c,1) != 0)
  247.         if((bp = slip_decode(dev,c)) != NULLBUF)
  248.             (*slip[dev].recv)(interface,bp);
  249.  
  250.     /* Kick the transmitter if it's idle */
  251.     if(stxrdy(dev))
  252.         asy_start(dev);
  253. }
  254. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  255.  * link level header
  256.  */
  257. slip_recv(interface,bp)
  258. struct interface *interface;
  259. struct mbuf *bp;
  260. {
  261.     void ip_route();
  262.  
  263.     /* By definition, all incoming packets are "addressed" to us */
  264.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  265.     ip_route(bp,0);
  266. }
  267. /* Attach a serial interface to the system
  268.  * argv[0]: hardware type, must be "asy"
  269.  * argv[1]: I/O address, e.g., "0x3f8"
  270.  * argv[2]: vector, e.g., "4"
  271.  * argv[3]: mode, may be:
  272.  *        "slip" (point-to-point SLIP)
  273.  *        "ax25" (AX.25 frame format in SLIP for raw TNC)
  274.  *        "slfp" (point-to-point SL/FP, as used by the Merit Network and MIT)
  275.  *          "nrs"  (net/rom to net/rom serial framing method)
  276.  * argv[4]: interface label, e.g., "sl0"
  277.  * argv[5]: receiver ring buffer size in bytes
  278.  * argv[6]: maximum transmission unit, bytes
  279.  * argv[7]: interface speed, e.g, "9600"
  280.  * argv[8]: optional, may be:
  281.  *        ax.25 callsign   DG2KK: new from netrom version
  282.  *        command string to MODEM, e.g. ATDT<phone number>
  283.  */
  284. asy_attach(argc,argv)
  285. int argc;
  286. char *argv[];
  287. {
  288.     register struct interface *if_asy;
  289.     extern struct interface *ifaces;
  290.     int16 dev;
  291.     char *call;        /* DG2KK: new from netrom version */
  292.     int mode;        /*  "  */
  293.     int asy_init();
  294.     int asy_send();
  295.     int doslip();
  296.     int asy_stop();
  297.     int ax_send();
  298.     int ax_output();
  299.     int kiss_recv();
  300.     int kiss_raw();
  301.  
  302.     if(nasy >= ASY_MAX){
  303.         printf("Too many asynch controllers\n");
  304.         return -1;
  305.     }
  306.     if(strcmp(argv[3],"slip") == 0)
  307.         mode = SLIP_MODE;
  308. #ifdef SLFP
  309.     else if(strcmp(argv[3],"slfp") == 0)
  310.         mode = SLFP_MODE;
  311. #endif
  312.     else if(strcmp(argv[3],"ax25") == 0)
  313.         mode = AX25_MODE;
  314. #ifdef    NRS
  315.     else if(strcmp(argv[3],"nrs") == 0)
  316.         mode = NRS_MODE;
  317. #endif
  318.     else {
  319.         printf("Mode %s unknown for interface %s\n",
  320.             argv[3],argv[4]);
  321.         return -1;
  322.     }
  323.     dev = nasy++;
  324. #ifdef UNIX /* BSD or SYS5 */
  325.     asy[dev].tty = malloc(strlen(argv[2])+1);
  326.     strcpy(asy[dev].tty, argv[2]);
  327. #else
  328.  
  329. #ifndef ATARI_ST
  330.     /* Initialize hardware-level control structure */
  331.     asy[dev].addr = htoi(argv[1]);
  332.     asy[dev].vec = htoi(argv[2]);
  333. #else
  334. /* -------- this is Atari-ST specific ---------(DG2KK)---------------------- */
  335.     /* argv[1] (COM Port address) is the Atari device name
  336.      *         (either "AUX:" or "MIDI")
  337.      * argv[2] (Interrupt vector) is used as a flag to indicate if 
  338.      *         bytes received on that interface should be sent out on
  339.      *         another interface (1 = AUX: 3 = MIDI).
  340.      */
  341.     asy[dev].vec = atoi(argv[2]);        /* dev to resend bytes to */
  342.     asy[dev].addr = 0;            /* use as error flag */
  343.     if (strcmp(argv[1],"AUX:") == 0) {
  344.         asy[dev].addr = 1;
  345.         /* don't allow retransmission on AUX: if mode is ax25! */
  346.         if (strcmp(argv[3],"ax25") == 0 && asy[dev].vec == 1) {
  347.             asy[dev].vec = 0;
  348.         }
  349.     }
  350.     if (strcmp(argv[1],"MIDI") == 0) {
  351.         asy[dev].addr = 3;
  352.     }
  353.     if (strcmp(argv[1],"CON:") == 0) {    /* this is pretty silly ! */
  354.         asy[dev].addr = 2;
  355.     }
  356.     if (asy[dev].addr == 0) {
  357.         return -1;
  358.     }
  359. /* ---------- end of Atari-specific stuff ------------------------------ */
  360. #endif /* ATARI_ST */
  361.  
  362. #endif    /* BSD or SYS5 */
  363.     /* Create interface structure and fill in details */
  364.     if_asy = (struct interface *)calloc(1,sizeof(struct interface));
  365.  
  366.     if_asy->name = malloc((unsigned)strlen(argv[4])+1);
  367.     strcpy(if_asy->name,argv[4]);
  368.     if_asy->mtu = atoi(argv[6]);
  369.     if_asy->dev = dev;
  370.     if_asy->recv = doslip;
  371.     if_asy->stop = asy_stop;
  372.  
  373.     if (argc == 9)
  374.         call = argv[8];
  375.     else
  376.         call = NULLCHAR;
  377.  
  378.     switch(mode){
  379.     case SLIP_MODE:
  380.         if_asy->ioctl = asy_ioctl;
  381.         if_asy->send = slip_send;
  382.         if_asy->output = NULLFP;    /* ARP isn't used */
  383.         if_asy->raw = slip_raw;
  384.         if_asy->flags = 0;
  385.         slip[dev].recv = slip_recv;
  386.         break;
  387. #ifdef    AX25
  388.     case AX25_MODE:
  389.         /* This function is done in main.c so it can be easily
  390.          * ifdef'ed out
  391.          */
  392.         if(kiss_attach(if_asy,&slip[dev].recv) == -1){
  393.             free(if_asy->name);
  394.             free((char *)if_asy);
  395.             nasy--;
  396.             return -1;
  397.         }
  398.         break;
  399. #endif
  400. #ifdef    NRS
  401.     case NRS_MODE:
  402.         if (nrs_attach(if_asy,call) == -1) {
  403.             free(if_asy->name);
  404.             free((char *)if_asy);
  405.             nasy--;
  406.             return -1;
  407.         }
  408.         nrs[dev].iface = if_asy; 
  409.         break;
  410. #endif
  411. #ifdef    SLFP
  412.     case SLFP_MODE:
  413.         if_asy->ioctl = asy_ioctl;
  414.         if_asy->send = slfp_send;
  415.         if_asy->recv = doslfp;
  416.         if_asy->output = NULLFP;    /* ARP isn't used */
  417.         if_asy->raw = slfp_raw;
  418.         if_asy->flags = 0;
  419.         slfp[dev].recv = slfp_recv;
  420.         break;
  421. #endif
  422.     }
  423.     if_asy->next = ifaces;
  424.     ifaces = if_asy;
  425.     asy_init(dev,(unsigned)atoi(argv[5]));
  426.     asy_speed(dev,atoi(argv[7]));
  427. #ifdef    SLFP
  428.     if(mode == SLFP_MODE)
  429.         if(slfp_init(if_asy, &ip_addr, argc>7?argv[8]:NULLCHAR) == -1) {
  430.         printf("Request for IP address timed out.\n");
  431.         asy_stop(if_asy);
  432.         ifaces = if_asy->next;
  433.         free((char *)if_asy);
  434.         return -1;
  435.         }
  436. #endif
  437.     return 0;
  438. }
  439.